<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { chatGetConversationMessagesService, chatGetRecentContactsService } from '@/api/chat'
import useGlobalConnection from '@/composables/index/globalConnection';
import { getFormattedDate, getFormattedDateTime } from '@/utils/date';
import { debounce } from '@/utils/lodash';

const props = defineProps({
  modelValue: { type: Boolean, default: false },
});

const emit = defineEmits(['update:modelValue'])


const chatDrawerVisible = computed({
  get: () => {
    if (props.modelValue) {
      if (contactList.value.length === 0) {
        getContactList();
      }
    }
    return props.modelValue;
  },
  set: (value) => {
    emit('update:modelValue', value)
  }
});

const newMessage = ref('');
const loadingMessages = ref(false);
const noMoreMessages = ref(false);

// 获取联系人列表
const contactList = ref([]);
const contactMap = reactive(new Map());
const contactIdxMap = reactive(new Map());
const getContactList = async () => {
  const result = await chatGetRecentContactsService();
  const contacts = result.data.data; 
  contactList.value.push(...contacts);

  for (let i = 0; i < contactList.value.length; i++) {
    const contact = contactList.value[i];
    // 会话id与会话的映射关系
    contactMap.set(contact.conversationId, contact);
    // 会话id与会话在列表中的索引的映射关系
    contactIdxMap.set(contact.conversationId, i);
  }
}

// 当前聊天对象
const activeContact = ref(null);

// 点击联系人
const clickContact = (contact) => {
  activeContact.value = contact;
  getMessages();
}

// 消息列表
const messages = reactive(new Map());

// 获取消息
let lastMinId = null;
const getMessages = async () => {
  const conversationId = activeContact.value.conversationId;
  return chatGetConversationMessagesService(conversationId, lastMinId).then((result) => {
    const newMessages = result.data.data;
    if (!messages.has(conversationId)) {
      messages.set(conversationId, []);
    }
    if (newMessages.length === 0) {
      noMoreMessages.value = true;
      return;
    }
    messages.get(conversationId).push(...newMessages);
    lastMinId = newMessages[newMessages.length - 1].id;
  })
}

// 处理实时消息
const handleChatMessage = (message) => {
  const { conversationId, senderId, content, sentTime } = JSON.parse(message.body);
  // 若会话列表还没获取过
  if (contactList.value.length === 0) {
    return;
  }
  // 若会话列表已经获取过但该会话的信息没有获取过
  if (!contactMap.has(conversationId)) {
    // 此时需要加载会话信息
    return;
  }

  // 构造消息对象
  const messageObj = {
    content: content,
    createdTime: sentTime,
    isUser: false
  }
  messages.get(conversationId).unshift(messageObj);

  // 更改会话状态（放到列表头部，修改未读数）
  const contact = contactList.value.splice(contactIdxMap.get(conversationId), 1)[0]
  contact.unreadCount++;
  contactList.value.unshift(contact);
  for (let i = 0; i < contactList.value.length; i++) {
    contactIdxMap.set(contactList.value[i].conversationId, i);
  }  
}
const { chatSend } = useGlobalConnection(handleChatMessage);

// 聊天内容滚动事件
const handleScroll = (e) => {
  const container = e.target;
  if (container.scrollTop - 150 <= container.clientHeight - container.scrollHeight) {
    loadMoreMessages();
  }
};

const debounceHandleScroll = debounce(handleScroll, 50);

// 加载更多消息
const loadMoreMessages = () => {
  if (loadingMessages.value || noMoreMessages.value) {
    return;
  }
  loadingMessages.value = true;

  getMessages().finally(() => {
    loadingMessages.value = false;
  })
};

// 发送消息
const sendMessage = () => {
  if (!newMessage.value.trim()) return;
  
  const conversationId = activeContact.value.conversationId
  const message = {
    conversationId: conversationId,
    content: newMessage.value,
    createdTime: getFormattedDateTime(),
    isUser: true
  };
  
  messages.get(conversationId).unshift(message);
  newMessage.value = '';

  chatSend(message);
};
</script>

<template>
  <el-drawer
    v-model="chatDrawerVisible"
    title="私信"
    direction="rtl"
    size="50%"
    class="chat-drawer"
  >
    <div class="chat-container">
      <!-- 联系人列表 -->
      <div class="contact-list">
        <div 
          v-for="contact in contactList" 
          :key="contact.contactId"
          class="contact-item"
          :class="{ 'active': contact.contactId === activeContact?.contactId }"
          @click="clickContact(contact)"
        >
          <el-avatar :src="contact.contactAvatar" fit="fill" size="large" />
          <div class="contact-info">
            <div class="contact-name">{{ contact.contactName }}</div>
            <div class="contact-last-message">{{ contact.lastMessage }}</div>
          </div>
          <div class="contact-meta">
            <div class="contact-time">{{ lastMessageTime }}</div>
            <el-badge :value="contact.unreadCount" class="contact-badge" v-if="contact.unreadCount > 0" />
          </div>
        </div>
      </div>
      
      <!-- 聊天区域 -->
      <div class="chat-area">        
        <!-- 消息列表（使用无限滚动） -->
        <div 
          class="message-list" 
          @scroll="debounceHandleScroll"
        >
          <div 
            v-for="message in messages.get(activeContact?.conversationId)" 
            :key="message.id"
            class="message-item"
            :class="{ 'user-message': message.isUser, 'other-message': !message.isUser }"
          >
            <div class="message-content">
              {{ message.content }}
            </div>
            <div class="message-time">{{ message.createdTime }}</div>
          </div>
          
          <div v-if="loadingMessages" class="loading-messages">
            <el-icon class="is-loading"><Loading /></el-icon>
            <span>加载中...</span>
          </div>
          
          <div v-if="noMoreMessages" class="no-more-messages">
            没有更多消息了
          </div>
        </div>
        
        <!-- 消息输入框 -->
        <div class="message-input">
          <el-input 
            v-model="newMessage" 
            placeholder="输入消息..." 
            @keyup.enter="sendMessage"
            resize="none"
            type="textarea"
            :autosize="{ minRows: 1, maxRows: 4 }"
          ></el-input>
          <el-button type="primary" @click="sendMessage" class="send-button">发送</el-button>
        </div>
      </div>
    </div>
  </el-drawer>
</template>


<style lang="scss" scoped>
  // 私信聊天样式
.chat-container {
  display: flex;
  height: 100%;
  background-color: #1a1c2d;
}

.contact-list {
  width: 35%;
  border-right: 1px solid #2d2f4a;
  overflow-y: auto;
}

.contact-item {
  display: flex;
  padding: 15px;
  cursor: pointer;
  transition: background-color 0.3s;
  border-bottom: 1px solid #2d2f4a;
  
  &:hover {
    background-color: #252840;
  }
  
  &.active {
    background-color: #303350;
  }
}

.contact-info {
  flex: 1;
  margin-left: 12px;
  overflow: hidden;
}

.contact-name {
  font-weight: 600;
  color: #e0e0ff;
  margin-bottom: 4px;
}

.contact-last-message {
  font-size: 12px;
  color: #8a8bb3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.contact-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

.contact-time {
  font-size: 11px;
  color: #6c6d8f;
  margin-bottom: 5px;
}

.contact-badge {
  margin-top: 5px;
}

.chat-area {
  display: flex;
  flex-direction: column;
  width: 65%;
  height: 100%;
}

.message-list {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
  display: flex;
  flex-direction: column-reverse;
}

.message-item {
  max-width: 75%;
  margin-bottom: 20px;
  animation: fadeIn 0.3s;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.user-message {
  margin-left: auto;
  
  .message-content {
    background-color: #4e6bff;
    color: white;
    border-radius: 18px 18px 4px 18px;
  }
}

.other-message {
  margin-right: auto;
  
  .message-content {
    background-color: #2d2f4a;
    color: #e0e0ff;
    border-radius: 18px 18px 18px 4px;
  }
}

.message-content {
  padding: 12px 16px;
  font-size: 14px;
  line-height: 1.5;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.message-time {
  font-size: 10px;
  color: #6c6d8f;
  margin-top: 5px;
  text-align: right;
}

.loading-messages, .no-more-messages {
  text-align: center;
  padding: 15px;
  color: #6c6d8f;
  font-size: 13px;
}

.message-input {
  padding: 15px;
  background-color: #1a1c2d;
  display: flex;
  align-items: center;
  border-top: 1px solid #2d2f4a;
  
  :deep(.el-textarea__inner) {
    background-color: #2d2f4a;
    border: none;
    color: #e0e0ff;
    padding-right: 60px;
  }
}

.send-button {
  margin-left: 10px;
  height: 36px;
}
</style>